/**
 * we-cropper v1.3.9
 * (c) 2020 dlhandsome
 * @license MIT
 */
'use strict'

var device = void 0
var TOUCH_STATE = ['touchstarted', 'touchmoved', 'touchended']

function firstLetterUpper(str) {
  return str.charAt(0).toUpperCase() + str.slice(1)
}

function setTouchState(instance) {
  var arg = [],
    len = arguments.length - 1
  while (len-- > 0) arg[len] = arguments[len + 1]

  TOUCH_STATE.forEach(function (key, i) {
    if (arg[i] !== undefined) {
      instance[key] = arg[i]
    }
  })
}

function validator(instance, o) {
  Object.defineProperties(instance, o)
}

function getDevice() {
  if (!device) {
    device = uni.getSystemInfoSync()
  }
  return device
}

var tmp = {}

var ref = getDevice()
var pixelRatio = ref.pixelRatio

var DEFAULT = {
  id: {
    default: 'cropper',
    get: function get() {
      return tmp.id
    },
    set: function set(value) {
      if (typeof value !== 'string') {
        console.error('id：' + value + ' is invalid')
      }
      tmp.id = value
    }
  },
  width: {
    default: 750,
    get: function get() {
      return tmp.width
    },
    set: function set(value) {
      if (typeof value !== 'number') {
        console.error('width：' + value + ' is invalid')
      }
      tmp.width = value
    }
  },
  height: {
    default: 750,
    get: function get() {
      return tmp.height
    },
    set: function set(value) {
      if (typeof value !== 'number') {
        console.error('height：' + value + ' is invalid')
      }
      tmp.height = value
    }
  },
  pixelRatio: {
    default: pixelRatio,
    get: function get() {
      return tmp.pixelRatio
    },
    set: function set(value) {
      if (typeof value !== 'number') {
        console.error('pixelRatio：' + value + ' is invalid')
      }
      tmp.pixelRatio = value
    }
  },
  scale: {
    default: 2.5,
    get: function get() {
      return tmp.scale
    },
    set: function set(value) {
      if (typeof value !== 'number') {
        console.error('scale：' + value + ' is invalid')
      }
      tmp.scale = value
    }
  },
  zoom: {
    default: 5,
    get: function get() {
      return tmp.zoom
    },
    set: function set(value) {
      if (typeof value !== 'number') {
        console.error('zoom：' + value + ' is invalid')
      } else if (value < 0 || value > 10) {
        console.error('zoom should be ranged in 0 ~ 10')
      }
      tmp.zoom = value
    }
  },
  src: {
    default: '',
    get: function get() {
      return tmp.src
    },
    set: function set(value) {
      if (typeof value !== 'string') {
        console.error('src：' + value + ' is invalid')
      }
      tmp.src = value
    }
  },
  cut: {
    default: {},
    get: function get() {
      return tmp.cut
    },
    set: function set(value) {
      if (typeof value !== 'object') {
        console.error('cut：' + value + ' is invalid')
      }
      tmp.cut = value
    }
  },
  boundStyle: {
    default: {},
    get: function get() {
      return tmp.boundStyle
    },
    set: function set(value) {
      if (typeof value !== 'object') {
        console.error('boundStyle：' + value + ' is invalid')
      }
      tmp.boundStyle = value
    }
  },
  onReady: {
    default: null,
    get: function get() {
      return tmp.ready
    },
    set: function set(value) {
      tmp.ready = value
    }
  },
  onBeforeImageLoad: {
    default: null,
    get: function get() {
      return tmp.beforeImageLoad
    },
    set: function set(value) {
      tmp.beforeImageLoad = value
    }
  },
  onImageLoad: {
    default: null,
    get: function get() {
      return tmp.imageLoad
    },
    set: function set(value) {
      tmp.imageLoad = value
    }
  },
  onBeforeDraw: {
    default: null,
    get: function get() {
      return tmp.beforeDraw
    },
    set: function set(value) {
      tmp.beforeDraw = value
    }
  }
}

var ref$1 = getDevice()
var windowWidth = ref$1.windowWidth

function prepare() {
  var self = this

  // v1.4.0 版本中将不再自动绑定we-cropper实例
  self.attachPage = function () {
    var pages = getCurrentPages()
    // 获取到当前page上下文
    var pageContext = pages[pages.length - 1]
    // 把this依附在Page上下文的wecropper属性上，便于在page钩子函数中访问
    Object.defineProperty(pageContext, 'wecropper', {
      get: function get() {
        console.warn(
          'Instance will not be automatically bound to the page after v1.4.0\n\n' +
            'Please use a custom instance name instead\n\n' +
            'Example: \n' +
            'this.mycropper = new WeCropper(options)\n\n' +
            '// ...\n' +
            'this.mycropper.getCropperImage()'
        )
        return self
      },
      configurable: true
    })
  }

  self.createCtx = function () {
    var id = self.id
    var targetId = self.targetId

    if (id) {
      self.ctx = self.ctx || uni.createCanvasContext(id)
      self.targetCtx = self.targetCtx || uni.createCanvasContext(targetId)
    } else {
      console.error("constructor: create canvas context failed, 'id' must be valuable")
    }
  }

  self.deviceRadio = windowWidth / 750
}

var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}

function createCommonjsModule(fn, module) {
  return (
    (module = {
      exports: {}
    }),
    fn(module, module.exports),
    module.exports
  )
}

var tools = createCommonjsModule(function (module, exports) {
  /**
   * String type check
   */
  exports.isStr = function (v) {
    return typeof v === 'string'
  }
  /**
   * Number type check
   */
  exports.isNum = function (v) {
    return typeof v === 'number'
  }
  /**
   * Array type check
   */
  exports.isArr = Array.isArray
  /**
   * undefined type check
   */
  exports.isUndef = function (v) {
    return v === undefined
  }

  exports.isTrue = function (v) {
    return v === true
  }

  exports.isFalse = function (v) {
    return v === false
  }
  /**
   * Function type check
   */
  exports.isFunc = function (v) {
    return typeof v === 'function'
  }
  /**
   * Quick object check - this is primarily used to tell
   * Objects from primitive values when we know the value
   * is a JSON-compliant type.
   */
  exports.isObj = exports.isObject = function (obj) {
    return obj !== null && typeof obj === 'object'
  }

  /**
   * Strict object type check. Only returns true
   * for plain JavaScript objects.
   */
  var _toString = Object.prototype.toString
  exports.isPlainObject = function (obj) {
    return _toString.call(obj) === '[object Object]'
  }

  /**
   * Check whether the object has the property.
   */
  var hasOwnProperty = Object.prototype.hasOwnProperty
  exports.hasOwn = function (obj, key) {
    return hasOwnProperty.call(obj, key)
  }

  /**
   * Perform no operation.
   * Stubbing args to make Flow happy without leaving useless transpiled code
   * with ...rest (https://flow.org/blog/2017/05/07/Strict-Function-Call-Arity/)
   */
  exports.noop = function (a, b, c) {}

  /**
   * Check if val is a valid array index.
   */
  exports.isValidArrayIndex = function (val) {
    var n = parseFloat(String(val))
    return n >= 0 && Math.floor(n) === n && isFinite(val)
  }
})

var tools_7 = tools.isFunc
var tools_10 = tools.isPlainObject

var EVENT_TYPE = ['ready', 'beforeImageLoad', 'beforeDraw', 'imageLoad']

function observer() {
  var self = this

  self.on = function (event, fn) {
    if (EVENT_TYPE.indexOf(event) > -1) {
      if (tools_7(fn)) {
        event === 'ready' ? fn(self) : (self['on' + firstLetterUpper(event)] = fn)
      }
    } else {
      console.error('event: ' + event + ' is invalid')
    }
    return self
  }
}

function wxPromise(fn) {
  return function (obj) {
    var args = [],
      len = arguments.length - 1
    while (len-- > 0) args[len] = arguments[len + 1]

    if (obj === void 0) obj = {}
    return new Promise(function (resolve, reject) {
      obj.success = function (res) {
        resolve(res)
      }
      obj.fail = function (err) {
        reject(err)
      }
      fn.apply(void 0, [obj].concat(args))
    })
  }
}

function draw(ctx, reserve) {
  if (reserve === void 0) reserve = false

  return new Promise(function (resolve) {
    ctx.draw(reserve, resolve)
  })
}

var getImageInfo = wxPromise(uni.getImageInfo)

var canvasToTempFilePath = wxPromise(uni.canvasToTempFilePath)

var base64 = createCommonjsModule(function (module, exports) {
  /*! http://mths.be/base64 v0.1.0 by @mathias | MIT license */
  (function (root) {
    // Detect free variables `exports`.
    var freeExports = 'object' == 'object' && exports

    // Detect free variable `module`.
    var freeModule = 'object' == 'object' && module && module.exports == freeExports && module

    // Detect free variable `global`, from Node.js or Browserified code, and use
    // it as `root`.
    var freeGlobal = typeof commonjsGlobal == 'object' && commonjsGlobal
    if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
      root = freeGlobal
    }

    /*--------------------------------------------------------------------------*/

    var InvalidCharacterError = function (message) {
      this.message = message
    }
    InvalidCharacterError.prototype = new Error()
    InvalidCharacterError.prototype.name = 'InvalidCharacterError'

    var error = function (message) {
      // Note: the error messages used throughout this file match those used by
      // the native `atob`/`btoa` implementation in Chromium.
      throw new InvalidCharacterError(message)
    }

    var TABLE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
    // http://whatwg.org/html/common-microsyntaxes.html#space-character
    var REGEX_SPACE_CHARACTERS = /[\t\n\f\r ]/g

    // `decode` is designed to be fully compatible with `atob` as described in the
    // HTML Standard. http://whatwg.org/html/webappapis.html#dom-windowbase64-atob
    // The optimized base64-decoding algorithm used is based on @atk’s excellent
    // implementation. https://gist.github.com/atk/1020396
    var decode = function (input) {
      input = String(input).replace(REGEX_SPACE_CHARACTERS, '')
      var length = input.length
      if (length % 4 == 0) {
        input = input.replace(/==?$/, '')
        length = input.length
      }
      if (
        length % 4 == 1 ||
        // http://whatwg.org/C#alphanumeric-ascii-characters
        /[^+a-zA-Z0-9/]/.test(input)
      ) {
        error('Invalid character: the string to be decoded is not correctly encoded.')
      }
      var bitCounter = 0
      var bitStorage
      var buffer
      var output = ''
      var position = -1
      while (++position < length) {
        buffer = TABLE.indexOf(input.charAt(position))
        bitStorage = bitCounter % 4 ? bitStorage * 64 + buffer : buffer
        // Unless this is the first of a group of 4 characters…
        if (bitCounter++ % 4) {
          // …convert the first 8 bits to a single ASCII character.
          output += String.fromCharCode(0xff & (bitStorage >> ((-2 * bitCounter) & 6)))
        }
      }
      return output
    }

    // `encode` is designed to be fully compatible with `btoa` as described in the
    // HTML Standard: http://whatwg.org/html/webappapis.html#dom-windowbase64-btoa
    var encode = function (input) {
      input = String(input)
      if (/[^\0-\xFF]/.test(input)) {
        // Note: no need to special-case astral symbols here, as surrogates are
        // matched, and the input is supposed to only contain ASCII anyway.
        error('The string to be encoded contains characters outside of the ' + 'Latin1 range.')
      }
      var padding = input.length % 3
      var output = ''
      var position = -1
      var a
      var b
      var c
      var buffer
      // Make sure any padding is handled outside of the loop.
      var length = input.length - padding

      while (++position < length) {
        // Read three bytes, i.e. 24 bits.
        a = input.charCodeAt(position) << 16
        b = input.charCodeAt(++position) << 8
        c = input.charCodeAt(++position)
        buffer = a + b + c
        // Turn the 24 bits into four chunks of 6 bits each, and append the
        // matching character for each of them to the output.
        output += TABLE.charAt((buffer >> 18) & 0x3f) + TABLE.charAt((buffer >> 12) & 0x3f) + TABLE.charAt((buffer >> 6) & 0x3f) + TABLE.charAt(buffer & 0x3f)
      }

      if (padding == 2) {
        a = input.charCodeAt(position) << 8
        b = input.charCodeAt(++position)
        buffer = a + b
        output += TABLE.charAt(buffer >> 10) + TABLE.charAt((buffer >> 4) & 0x3f) + TABLE.charAt((buffer << 2) & 0x3f) + '='
      } else if (padding == 1) {
        buffer = input.charCodeAt(position)
        output += TABLE.charAt(buffer >> 2) + TABLE.charAt((buffer << 4) & 0x3f) + '=='
      }

      return output
    }

    var base64 = {
      encode: encode,
      decode: decode,
      version: '0.1.0'
    }

    // Some AMD build optimizers, like r.js, check for specific condition patterns
    // like the following:
    if (typeof undefined == 'function' && typeof undefined.amd == 'object' && undefined.amd) {
      undefined(function () {
        return base64
      })
    } else if (freeExports && !freeExports.nodeType) {
      if (freeModule) {
        // in Node.js or RingoJS v0.8.0+
        freeModule.exports = base64
      } else {
        // in Narwhal or RingoJS v0.7.0-
        for (var key in base64) {
          base64.hasOwnProperty(key) && (freeExports[key] = base64[key])
        }
      }
    } else {
      // in Rhino or a web browser
      root.base64 = base64
    }
  })(commonjsGlobal)
})

function makeURI(strData, type) {
  return 'data:' + type + ';base64,' + strData
}

function fixType(type) {
  type = type.toLowerCase().replace(/jpg/i, 'jpeg')
  var r = type.match(/png|jpeg|bmp|gif/)[0]
  return 'image/' + r
}

function encodeData(data) {
  var str = ''
  if (typeof data === 'string') {
    str = data
  } else {
    for (var i = 0; i < data.length; i++) {
      str += String.fromCharCode(data[i])
    }
  }
  return base64.encode(str)
}

/**
 * 获取图像区域隐含的像素数据
 * @param canvasId canvas标识
 * @param x 将要被提取的图像数据矩形区域的左上角 x 坐标
 * @param y 将要被提取的图像数据矩形区域的左上角 y 坐标
 * @param width 将要被提取的图像数据矩形区域的宽度
 * @param height 将要被提取的图像数据矩形区域的高度
 * @param done 完成回调
 */
function getImageData(canvasId, x, y, width, height, done) {
  uni.canvasGetImageData({
    canvasId: canvasId,
    x: x,
    y: y,
    width: width,
    height: height,
    success: function success(res) {
      done(res, null)
    },
    fail: function fail(res) {
      done(null, res)
    }
  })
}

/**
 * 生成bmp格式图片
 * 按照规则生成图片响应头和响应体
 * @param oData 用来描述 canvas 区域隐含的像素数据 { data, width, height } = oData
 * @returns {*} base64字符串
 */
function genBitmapImage(oData) {
  //
  // BITMAPFILEHEADER: http://msdn.microsoft.com/en-us/library/windows/desktop/dd183374(v=vs.85).aspx
  // BITMAPINFOHEADER: http://msdn.microsoft.com/en-us/library/dd183376.aspx
  //
  var biWidth = oData.width
  var biHeight = oData.height
  var biSizeImage = biWidth * biHeight * 3
  var bfSize = biSizeImage + 54 // total header size = 54 bytes

  //
  //  typedef struct tagBITMAPFILEHEADER {
  //  	WORD bfType;
  //  	DWORD bfSize;
  //  	WORD bfReserved1;
  //  	WORD bfReserved2;
  //  	DWORD bfOffBits;
  //  } BITMAPFILEHEADER;
  //
  var BITMAPFILEHEADER = [
    // WORD bfType -- The file type signature; must be "BM"
    0x42,
    0x4d,
    // DWORD bfSize -- The size, in bytes, of the bitmap file
    bfSize & 0xff,
    (bfSize >> 8) & 0xff,
    (bfSize >> 16) & 0xff,
    (bfSize >> 24) & 0xff,
    // WORD bfReserved1 -- Reserved; must be zero
    0,
    0,
    // WORD bfReserved2 -- Reserved; must be zero
    0,
    0,
    // DWORD bfOffBits -- The offset, in bytes, from the beginning of the BITMAPFILEHEADER structure to the bitmap bits.
    54,
    0,
    0,
    0
  ]

  //
  //  typedef struct tagBITMAPINFOHEADER {
  //  	DWORD biSize;
  //  	LONG  biWidth;
  //  	LONG  biHeight;
  //  	WORD  biPlanes;
  //  	WORD  biBitCount;
  //  	DWORD biCompression;
  //  	DWORD biSizeImage;
  //  	LONG  biXPelsPerMeter;
  //  	LONG  biYPelsPerMeter;
  //  	DWORD biClrUsed;
  //  	DWORD biClrImportant;
  //  } BITMAPINFOHEADER, *PBITMAPINFOHEADER;
  //
  var BITMAPINFOHEADER = [
    // DWORD biSize -- The number of bytes required by the structure
    40,
    0,
    0,
    0,
    // LONG biWidth -- The width of the bitmap, in pixels
    biWidth & 0xff,
    (biWidth >> 8) & 0xff,
    (biWidth >> 16) & 0xff,
    (biWidth >> 24) & 0xff,
    // LONG biHeight -- The height of the bitmap, in pixels
    biHeight & 0xff,
    (biHeight >> 8) & 0xff,
    (biHeight >> 16) & 0xff,
    (biHeight >> 24) & 0xff,
    // WORD biPlanes -- The number of planes for the target device. This value must be set to 1
    1,
    0,
    // WORD biBitCount -- The number of bits-per-pixel, 24 bits-per-pixel -- the bitmap
    // has a maximum of 2^24 colors (16777216, Truecolor)
    24,
    0,
    // DWORD biCompression -- The type of compression, BI_RGB (code 0) -- uncompressed
    0,
    0,
    0,
    0,
    // DWORD biSizeImage -- The size, in bytes, of the image. This may be set to zero for BI_RGB bitmaps
    biSizeImage & 0xff,
    (biSizeImage >> 8) & 0xff,
    (biSizeImage >> 16) & 0xff,
    (biSizeImage >> 24) & 0xff,
    // LONG biXPelsPerMeter, unused
    0,
    0,
    0,
    0,
    // LONG biYPelsPerMeter, unused
    0,
    0,
    0,
    0,
    // DWORD biClrUsed, the number of color indexes of palette, unused
    0,
    0,
    0,
    0,
    // DWORD biClrImportant, unused
    0,
    0,
    0,
    0
  ]

  var iPadding = (4 - ((biWidth * 3) % 4)) % 4

  var aImgData = oData.data

  var strPixelData = ''
  var biWidth4 = biWidth << 2
  var y = biHeight
  var fromCharCode = String.fromCharCode

  do {
    var iOffsetY = biWidth4 * (y - 1)
    var strPixelRow = ''
    for (var x = 0; x < biWidth; x++) {
      var iOffsetX = x << 2
      strPixelRow +=
        fromCharCode(aImgData[iOffsetY + iOffsetX + 2]) + fromCharCode(aImgData[iOffsetY + iOffsetX + 1]) + fromCharCode(aImgData[iOffsetY + iOffsetX])
    }

    for (var c = 0; c < iPadding; c++) {
      strPixelRow += String.fromCharCode(0)
    }

    strPixelData += strPixelRow
  } while (--y)

  var strEncoded = encodeData(BITMAPFILEHEADER.concat(BITMAPINFOHEADER)) + encodeData(strPixelData)

  return strEncoded
}

/**
 * 转换为图片base64
 * @param canvasId canvas标识
 * @param x 将要被提取的图像数据矩形区域的左上角 x 坐标
 * @param y 将要被提取的图像数据矩形区域的左上角 y 坐标
 * @param width 将要被提取的图像数据矩形区域的宽度
 * @param height 将要被提取的图像数据矩形区域的高度
 * @param type 转换图片类型
 * @param done 完成回调
 */
function convertToImage(canvasId, x, y, width, height, type, done) {
  if (done === void 0) done = function () {}

  if (type === undefined) {
    type = 'png'
  }
  type = fixType(type)
  if (/bmp/.test(type)) {
    getImageData(canvasId, x, y, width, height, function (data, err) {
      var strData = genBitmapImage(data)
      tools_7(done) && done(makeURI(strData, 'image/' + type), err)
    })
  } else {
    console.error("暂不支持生成'" + type + "'类型的base64图片")
  }
}

var CanvasToBase64 = {
  convertToImage: convertToImage,
  // convertToPNG: function (width, height, done) {
  //   return convertToImage(width, height, 'png', done)
  // },
  // convertToJPEG: function (width, height, done) {
  //   return convertToImage(width, height, 'jpeg', done)
  // },
  // convertToGIF: function (width, height, done) {
  //   return convertToImage(width, height, 'gif', done)
  // },
  convertToBMP: function (ref, done) {
    if (ref === void 0) ref = {}
    var canvasId = ref.canvasId
    var x = ref.x
    var y = ref.y
    var width = ref.width
    var height = ref.height
    if (done === void 0) done = function () {}

    return convertToImage(canvasId, x, y, width, height, 'bmp', done)
  }
}

function methods() {
  var self = this

  var boundWidth = self.width // 裁剪框默认宽度，即整个画布宽度
  var boundHeight = self.height // 裁剪框默认高度，即整个画布高度

  var id = self.id
  var targetId = self.targetId
  var pixelRatio = self.pixelRatio

  var ref = self.cut
  var x = ref.x
  if (x === void 0) x = 0
  var y = ref.y
  if (y === void 0) y = 0
  var width = ref.width
  if (width === void 0) width = boundWidth
  var height = ref.height
  if (height === void 0) height = boundHeight

  self.updateCanvas = function (done) {
    if (self.croperTarget) {
      //  画布绘制图片
      self.ctx.drawImage(self.croperTarget, self.imgLeft, self.imgTop, self.scaleWidth, self.scaleHeight)
    }
    tools_7(self.onBeforeDraw) && self.onBeforeDraw(self.ctx, self)

    self.setBoundStyle(self.boundStyle) //	设置边界样式

    self.ctx.draw(false, done)
    return self
  }

  self.pushOrigin = self.pushOrign = function (src) {
    self.src = src

    tools_7(self.onBeforeImageLoad) && self.onBeforeImageLoad(self.ctx, self)

    return getImageInfo({
      src: src
    })
      .then(function (res) {
        var innerAspectRadio = res.width / res.height
        var customAspectRadio = width / height

        self.croperTarget = res.path

        if (innerAspectRadio < customAspectRadio) {
          self.rectX = x
          self.baseWidth = width
          self.baseHeight = width / innerAspectRadio
          self.rectY = y - Math.abs((height - self.baseHeight) / 2)
        } else {
          self.rectY = y
          self.baseWidth = height * innerAspectRadio
          self.baseHeight = height
          self.rectX = x - Math.abs((width - self.baseWidth) / 2)
        }

        self.imgLeft = self.rectX
        self.imgTop = self.rectY
        self.scaleWidth = self.baseWidth
        self.scaleHeight = self.baseHeight

        self.update()

        return new Promise(function (resolve) {
          self.updateCanvas(resolve)
        })
      })
      .then(function () {
        tools_7(self.onImageLoad) && self.onImageLoad(self.ctx, self)
      })
  }

  self.removeImage = function () {
    self.src = ''
    self.croperTarget = ''
    return draw(self.ctx)
  }

  self.getCropperBase64 = function (done) {
    if (done === void 0) done = function () {}

    CanvasToBase64.convertToBMP(
      {
        canvasId: id,
        x: x,
        y: y,
        width: width,
        height: height
      },
      done
    )
  }

  self.getCropperImage = function (opt, fn) {
    var customOptions = opt

    var canvasOptions = {
      canvasId: id,
      x: x,
      y: y,
      width: width,
      height: height
    }

    var task = function () {
      return Promise.resolve()
    }

    if (tools_10(customOptions) && customOptions.original) {
      // original mode
      task = function () {
        self.targetCtx.drawImage(
          self.croperTarget,
          self.imgLeft * pixelRatio,
          self.imgTop * pixelRatio,
          self.scaleWidth * pixelRatio,
          self.scaleHeight * pixelRatio
        )

        canvasOptions = {
          canvasId: targetId,
          x: x * pixelRatio,
          y: y * pixelRatio,
          width: width * pixelRatio,
          height: height * pixelRatio
        }

        return draw(self.targetCtx)
      }
    }

    return task()
      .then(function () {
        if (tools_10(customOptions)) {
          canvasOptions = Object.assign({}, canvasOptions, customOptions)
        }

        if (tools_7(customOptions)) {
          fn = customOptions
        }

        var arg = canvasOptions.componentContext ? [canvasOptions, canvasOptions.componentContext] : [canvasOptions]

        return canvasToTempFilePath.apply(null, arg)
      })
      .then(function (res) {
        var tempFilePath = res.tempFilePath

        return tools_7(fn) ? fn.call(self, tempFilePath, null) : tempFilePath
      })
      .catch(function (err) {
        if (tools_7(fn)) {
          fn.call(self, null, err)
        } else {
          throw err
        }
      })
  }
}

/**
 * 获取最新缩放值
 * @param oldScale 上一次触摸结束后的缩放值
 * @param oldDistance 上一次触摸结束后的双指距离
 * @param zoom 缩放系数
 * @param touch0 第一指touch对象
 * @param touch1 第二指touch对象
 * @returns {*}
 */
var getNewScale = function (oldScale, oldDistance, zoom, touch0, touch1) {
  var xMove, yMove, newDistance
  // 计算二指最新距离
  xMove = Math.round(touch1.x - touch0.x)
  yMove = Math.round(touch1.y - touch0.y)
  newDistance = Math.round(Math.sqrt(xMove * xMove + yMove * yMove))

  return oldScale + 0.001 * zoom * (newDistance - oldDistance)
}

function update() {
  var self = this

  if (!self.src) {
    return
  }

  self.__oneTouchStart = function (touch) {
    self.touchX0 = Math.round(touch.x)
    self.touchY0 = Math.round(touch.y)
  }

  self.__oneTouchMove = function (touch) {
    var xMove, yMove
    // 计算单指移动的距离
    if (self.touchended) {
      return self.updateCanvas()
    }
    xMove = Math.round(touch.x - self.touchX0)
    yMove = Math.round(touch.y - self.touchY0)

    var imgLeft = Math.round(self.rectX + xMove)
    var imgTop = Math.round(self.rectY + yMove)

    self.outsideBound(imgLeft, imgTop)

    self.updateCanvas()
  }

  self.__twoTouchStart = function (touch0, touch1) {
    var xMove, yMove, oldDistance

    self.touchX1 = Math.round(self.rectX + self.scaleWidth / 2)
    self.touchY1 = Math.round(self.rectY + self.scaleHeight / 2)

    // 计算两指距离
    xMove = Math.round(touch1.x - touch0.x)
    yMove = Math.round(touch1.y - touch0.y)
    oldDistance = Math.round(Math.sqrt(xMove * xMove + yMove * yMove))

    self.oldDistance = oldDistance
  }

  self.__twoTouchMove = function (touch0, touch1) {
    var oldScale = self.oldScale
    var oldDistance = self.oldDistance
    var scale = self.scale
    var zoom = self.zoom

    self.newScale = getNewScale(oldScale, oldDistance, zoom, touch0, touch1)

    //  设定缩放范围
    self.newScale <= 1 && (self.newScale = 1)
    self.newScale >= scale && (self.newScale = scale)

    self.scaleWidth = Math.round(self.newScale * self.baseWidth)
    self.scaleHeight = Math.round(self.newScale * self.baseHeight)
    var imgLeft = Math.round(self.touchX1 - self.scaleWidth / 2)
    var imgTop = Math.round(self.touchY1 - self.scaleHeight / 2)

    self.outsideBound(imgLeft, imgTop)

    self.updateCanvas()
  }

  self.__xtouchEnd = function () {
    self.oldScale = self.newScale
    self.rectX = self.imgLeft
    self.rectY = self.imgTop
  }
}

var handle = {
  //  图片手势初始监测
  touchStart: function touchStart(e) {
    var self = this
    var ref = e.touches
    var touch0 = ref[0]
    var touch1 = ref[1]

    if (!self.src) {
      return
    }

    setTouchState(self, true, null, null)

    // 计算第一个触摸点的位置，并参照改点进行缩放
    self.__oneTouchStart(touch0)

    // 两指手势触发
    if (e.touches.length >= 2) {
      self.__twoTouchStart(touch0, touch1)
    }
  },

  //  图片手势动态缩放
  touchMove: function touchMove(e) {
    var self = this
    var ref = e.touches
    var touch0 = ref[0]
    var touch1 = ref[1]

    if (!self.src) {
      return
    }

    setTouchState(self, null, true)

    // 单指手势时触发
    if (e.touches.length === 1) {
      self.__oneTouchMove(touch0)
    }
    // 两指手势触发
    if (e.touches.length >= 2) {
      self.__twoTouchMove(touch0, touch1)
    }
  },

  touchEnd: function touchEnd(e) {
    var self = this

    if (!self.src) {
      return
    }

    setTouchState(self, false, false, true)
    self.__xtouchEnd()
  }
}

function cut() {
  var self = this
  var boundWidth = self.width // 裁剪框默认宽度，即整个画布宽度
  var boundHeight = self.height
  // 裁剪框默认高度，即整个画布高度
  var ref = self.cut
  var x = ref.x
  if (x === void 0) x = 0
  var y = ref.y
  if (y === void 0) y = 0
  var width = ref.width
  if (width === void 0) width = boundWidth
  var height = ref.height
  if (height === void 0) height = boundHeight

  /**
   * 设置边界
   * @param imgLeft 图片左上角横坐标值
   * @param imgTop 图片左上角纵坐标值
   */
  self.outsideBound = function (imgLeft, imgTop) {
    self.imgLeft = imgLeft >= x ? x : self.scaleWidth + imgLeft - x <= width ? x + width - self.scaleWidth : imgLeft

    self.imgTop = imgTop >= y ? y : self.scaleHeight + imgTop - y <= height ? y + height - self.scaleHeight : imgTop
  }

  /**
   * 设置边界样式
   * @param color	边界颜色
   */
  self.setBoundStyle = function (ref) {
    if (ref === void 0) ref = {}
    var color = ref.color
    if (color === void 0) color = '#04b00f'
    var mask = ref.mask
    if (mask === void 0) mask = 'rgba(0, 0, 0, 0.3)'
    var lineWidth = ref.lineWidth
    if (lineWidth === void 0) lineWidth = 1

    var half = lineWidth / 2
    var boundOption = [
      {
        start: {
          x: x - half,
          y: y + 10 - half
        },
        step1: {
          x: x - half,
          y: y - half
        },
        step2: {
          x: x + 10 - half,
          y: y - half
        }
      },
      {
        start: {
          x: x - half,
          y: y + height - 10 + half
        },
        step1: {
          x: x - half,
          y: y + height + half
        },
        step2: {
          x: x + 10 - half,
          y: y + height + half
        }
      },
      {
        start: {
          x: x + width - 10 + half,
          y: y - half
        },
        step1: {
          x: x + width + half,
          y: y - half
        },
        step2: {
          x: x + width + half,
          y: y + 10 - half
        }
      },
      {
        start: {
          x: x + width + half,
          y: y + height - 10 + half
        },
        step1: {
          x: x + width + half,
          y: y + height + half
        },
        step2: {
          x: x + width - 10 + half,
          y: y + height + half
        }
      }
    ]

    // 绘制半透明层
    self.ctx.beginPath()
    self.ctx.setFillStyle(mask)
    self.ctx.fillRect(0, 0, x, boundHeight)
    self.ctx.fillRect(x, 0, width, y)
    self.ctx.fillRect(x, y + height, width, boundHeight - y - height)
    self.ctx.fillRect(x + width, 0, boundWidth - x - width, boundHeight)
    self.ctx.fill()

    boundOption.forEach(function (op) {
      self.ctx.beginPath()
      self.ctx.setStrokeStyle(color)
      self.ctx.setLineWidth(lineWidth)
      self.ctx.moveTo(op.start.x, op.start.y)
      self.ctx.lineTo(op.step1.x, op.step1.y)
      self.ctx.lineTo(op.step2.x, op.step2.y)
      self.ctx.stroke()
    })
  }
}

var version = '1.3.9'

var WeCropper = function WeCropper(params) {
  var self = this
  var _default = {}

  validator(self, DEFAULT)

  Object.keys(DEFAULT).forEach(function (key) {
    _default[key] = DEFAULT[key].default
  })
  Object.assign(self, _default, params)

  self.prepare()
  self.attachPage()
  self.createCtx()
  self.observer()
  self.cutt()
  self.methods()
  self.init()
  self.update()

  return self
}

WeCropper.prototype.init = function init() {
  var self = this
  var src = self.src

  self.version = version

  typeof self.onReady === 'function' && self.onReady(self.ctx, self)

  if (src) {
    self.pushOrign(src)
  } else {
    self.updateCanvas()
  }
  setTouchState(self, false, false, false)

  self.oldScale = 1
  self.newScale = 1

  return self
}

Object.assign(WeCropper.prototype, handle)

WeCropper.prototype.prepare = prepare
WeCropper.prototype.observer = observer
WeCropper.prototype.methods = methods
WeCropper.prototype.cutt = cut
WeCropper.prototype.update = update

export default WeCropper
